module command.StartAppCommand;

import std.stdio;

import std.string;
import hunt.console.helper.QuestionHelper;
import hunt.console.input.Input;
import hunt.console.input.InputArgument;
import hunt.console.output.Output;
import hunt.console.question.Question;
import hunt.console.command.Command;
import std.file;
import hunt.util.Serialize;
import config.ConfigurationDefine;
import hunt.logging;
import msgtrans;
import client.MsgServerClient;
import client.LogicServerClient;
import message.Constants;
import core.thread;
import std.conv :to ;
import message.MsgDefine;
import google.protobuf;
import std.array;
import client.GateServerClient;


class StartAppCommand : Command
{
  enum string configPath = "./config_test.json";

  __gshared string selfId ;


  static string getSelfId()
  {
      return selfId;
  }

  private MsgConfig _config;

  override protected void configure()
  {
    this
    .setName("start")
    .setDescription("Outputs a start.")
    .addArgument("config", InputArgument.OPTIONAL, "Name of the person to greet")
    ;
  }

  override protected int execute(Input input, Output output)
  {
    string name = input.getArgument("config");
    if (name is null) {
      name = "stranger";
    }

    parseConfig(name);
    initLog();
    startApp();
    return 0;
  }

  override protected void interact(Input input, Output output)
  {
    if (input.getArgument("config") is null) {
      //string name = (cast(QuestionHelper) (getHelper("question")))
      //.ask(input, output, new Question("What is your name?"));
       input.setArgument("config", configPath);
       output.writeln(format("Not specified config use default config %s", configPath));
    }
    else
    {
      output.writeln(format("start app with config : %s", input.getArgument("config")));
    }
  }

  private void parseConfig(string path)
  {
    string data = readText(path);
    _config = toOBJ!MsgConfig(parseJSON(data));
    Config.getInstance().setConfig(_config);
    selfId = to!string(_config.id);
  }


  private void initLog()
  {
    LogConf conf;
    conf.fileName = Config.getInstance().getConfig().log;
    logLoadConf(conf);
  }

  private void startApp()
  {
    foreach(LogicServerConf c ; _config.logicserver)
    {
      while(true)
      {
        MessageTransportClient client = new MessageTransportClient(LogicClientName);
        client.channel(new TcpClientChannel(c.host, cast(ushort)c.port));
        client.closer((TransportContext t){
          Thread.sleep(2.seconds);
          while (true)
          {
            client.connect();
            logInfo("isConnected :%s",client.isConnected );
            if(client.isConnected)
            {
              client.send(new MessageBuffer(MESSAGE.CMD_REGISTER_MSGSERVER , cast(ubyte[])(StartAppCommand.getSelfId)));
              break;
            }
            Thread.sleep(2.seconds);
          }
        });
        client.connect();
        if(client.isConnected)
        {
          client.send(new MessageBuffer(MESSAGE.CMD_REGISTER_MSGSERVER , cast(ubyte[])(to!string(_config.id))));
          LogicServerClient.getInstance().addForwardClient(c.id,client);
          break;
        }
        Thread.sleep(2.seconds);
      }

    }

    initChatMap();

    MessageTransportServer server = new MessageTransportServer(MsgServerName);

    server.addChannel(new TcpServerChannel(cast(ushort)_config.tcpport));

    server.acceptor((TransportContext ctx) {
      infof("New connection: id=%d", ctx.id());
    });

    server.closer((TransportContext ctx) {
        GateServerClient.getInstance().deleForwardClient(ctx.id);
    });

    server.start();

    foreach(MsgServerConf c ; _config.msgserver)
    {
      if (_config.id == c.id)
      {
        logInfo("config.id: %d   c.id : %d",_config.id,c.id);
        MsgServerClient.getInstance.addForwardClient(c.id,null);
        continue;
      }
      while (true) {
        MessageTransportClient client = new MessageTransportClient(MsgClientName);
        client.channel(new TcpClientChannel(c.host, cast(ushort)c.port));
        client.connect();
        if (client.isConnected)
        {
          client.send(new MessageBuffer(MESSAGE.CMD_REGISTER_MSGSERVER , []));
          MsgServerClient.getInstance.addForwardClient(c.id,client);
          break;
        }
        Thread.sleep(2.seconds);
      }
    }
  }

private void initChatMap()
{
    int index = selfHashIndex();
    g_msgServerIndex = index;
    MessageTransportClient logicClient =  LogicServerClient.getInstance().getForwardClient();
    InitChatMap req = new InitChatMap();
    req.index = index;
    req.size = cast(int)(_config.msgserver.length);
    g_msgServerSize = req.size;
    logicClient.send(new MessageBuffer(MESSAGE.CMD_INITCHATMAP, req.toProtobuf.array));
    logInfo("send initChatMap-----");
}

private int selfHashIndex()
{
    int i = 0;
    foreach (MsgServerConf c ; _config.msgserver)
    {
      if (_config.id == c.id)
      {
          break;
      }
      i++;
    }
    return i;
}

}

